Programming languages - application and interpretation

نویسنده

  • Shriram Krishnamurthi
چکیده

ion has, however, been compromised by the aliasing, and accidental side-effects can leak into the calling contexts, exposing unnecessary implementation details of the procedure. In the early days of programming language design, before programs were particularly sophisticated, the ability to write simple abstractions such as swap was considered valuable (since it is used, for instance, in the implementation of some sorting algorithms). Today, however, we recognize that such abstractions are rather meager in the face of the needs of modern systems. We pay greater attention, instead, to the need for creating useful abstraction boundaries between units of modularity such as procedures: the fewer hidden interactions they have, and the less they interfere with one another, the more easily we can reason about their behavior in isolation. Exercise 14.3.1 While call-by-value preserves the value of variables in the calling context, it does not protect all values. In particular, in many call-by-value languages, a composite data structure (such as a vector) passed as an argument may be mutated by the callee, with the effects visible to the caller. 1. Does this behavior contradict the claim that the language is passing “values” as arguments? Use our investigation of mutable data structures in Section 13 to make your argument rigorous. Hint: Implement an interpreter for a language with both boxes and call-by-reference application, then argue about similarities and differences. 2. Languages like ML tackle this problem by forcing programmers to annotate all mutable data structures using references, the ML counterpart to boxes. Any data structure not so mutated is considered immutable. What trade-offs does ML’s design introduce? Exercise 14.3.2 There appears to be a neutral ground between call-by-value and call-by-reference. Consider the following proposed syntax: {with {swap {fun {x} {fun {y} {with {z x} {seqn {set x y} {set y z}}}}}} {with {a 3} {with {b 2} {seqn {{swap {ref a}} {ref b}} b}}}} The ref notation is an indicator to the interpreter to pass the variable’s location rather than its value; that is, by using {ref a} and {ref b}, the invoker of the procedure indicates his willingness to have his variables be aliased and thus, potentially, be mutated. 1. Modify the interpreter to support the use of ref for procedure arguments. 2. Does this proposal result in a procedural abstraction of the process of swapping the values of two variables? If it does, this would reconcile the design tension between the two invocation techniques: it avoids the difficulty of call-by-value (the inability to write a swap procedure) as well as that of call-by-reference (aliasing of parameters without the caller’s knowledge). Discuss. 140 CHAPTER 14. VARIABLES 3. Suppose programmers are allowed to apply ref to variables elsewhere in the program. What type should the interpreter use to represent the resulting value? How does this compare to an l-value? Does this introduce the need for additional operators in the language? How does this relate to the & operator in C? 14.3. PERSPECTIVE 141 (define-type VCFAE-Value [numV (n number?)] [closureV (param symbol?) (body VCFAE?) (env Env?)]) ;; interp : VCFAE Env Store→ Value×Store (define (interp expr env store) (type-case VCFAE expr [num (n) (v×s (numV n) store)] [add (l r) (type-case Value×Store (interp l env store) [v×s (l-value l-store) (type-case Value×Store (interp r env l-store) [v×s (r-value r-store) (v×s (num+ l-value r-value) r-store)])])] [id (v) (v×s (store-lookup (env-lookup v env) store) store)] [fun (bound-id bound-body) (v×s (closureV bound-id bound-body env) store)] .. Figure 14.1: Implementing Variables, Part 1 142 CHAPTER 14. VARIABLES .. [app (fun-expr arg-expr) (type-case Value×Store (interp fun-expr env store) [v×s (fun-value fun-store) (type-case Value×Store (interp arg-expr env fun-store) [v×s (arg-value arg-store) (local ([define new-loc (next-location arg-store)]) (interp (closureV-body fun-value) (aSub (closureV-param fun-value) new-loc (closureV-env fun-value)) (aSto new-loc arg-value arg-store)))])])] [if0 (test truth falsity) (type-case Value×Store (interp test env store) [v×s (test-value test-store) (if (num-zero? test-value) (interp truth env test-store) (interp falsity env test-store))])] [set (var value) (type-case Value×Store (interp value env store) [v×s (value-value value-store) (local ([define the-loc (env-lookup var env)]) (v×s value-value (aSto the-loc value-value value-store)))])] [seqn (e1 e2) (type-case Value×Store (interp e1 env store) [v×s (e1-value e1-store) (interp e2 env e1-store)])])) Figure 14.2: Implementing Variables, Part 2 14.3. PERSPECTIVE 143 (define-type RVCFAE-Value [numV (n number?)] [closureV (param symbol?) (body RVCFAE?) (env Env?)] [refclosV (param symbol?) (body RVCFAE?) (env Env?)]) ;; interp : RVCFAE Env Store→ Value×Store (define (interp expr env store) (type-case RVCFAE expr [num (n) (v×s (numV n) store)] [add (l r) (type-case Value×Store (interp l env store) [v×s (l-value l-store) (type-case Value×Store (interp r env l-store) [v×s (r-value r-store) (v×s (num+ l-value r-value) r-store)])])] [id (v) (v×s (store-lookup (env-lookup v env) store) store)] [if0 (test pass fail) (type-case Value×Store (interp test env store) [v×s (test-value test-store) (if (num-zero? test-value) (interp pass env test-store) (interp fail env test-store))])] [fun (bound-id bound-body) (v×s (closureV bound-id bound-body env) store)] [refun (bound-id bound-body) (v×s (refclosV bound-id bound-body env) store)] .. Figure 14.3: Implementing Call-by-Reference, Part 1 144 CHAPTER 14. VARIABLES .. [app (fun-expr arg-expr) (type-case Value×Store (interp fun-expr env store) [v×s (fun-value fun-store) (type-case RVCFAE-Value fun-value [closureV (cl-param cl-body cl-env) (type-case Value×Store (interp arg-expr env fun-store) [v×s (arg-value arg-store) (local ([define new-loc (next-location arg-store)]) (interp cl-body (aSub cl-param new-loc cl-env) (aSto new-loc arg-value arg-store)))])] [refclosV (cl-param cl-body cl-env) (local ([define arg-loc (env-lookup (id-name arg-expr) env)]) (interp cl-body (aSub cl-param arg-loc cl-env) fun-store))] [numV ( ) (error ’interp ”trying to apply a number”)])])] [set (var value) (type-case Value×Store (interp value env store) [v×s (value-value value-store) (local ([define the-loc (env-lookup var env)]) (v×s value-value (aSto the-loc value-value value-store)))])] [seqn (e1 e2) (type-case Value×Store (interp e1 env store) [v×s (e1-value e1-store) (interp e2 env e1-store)])])) Figure 14.4: Implementing Call-by-Reference, Part 2

برای دانلود رایگان متن کامل این مقاله و بیش از 32 میلیون مقاله دیگر ابتدا ثبت نام کنید

ثبت نام

اگر عضو سایت هستید لطفا وارد حساب کاربری خود شوید

منابع مشابه

Theoretical Foundations for Practical ‘Totally Functional Programming’

Interpretation is an implicit part of today’s programming; it has great power but is overused and has significant costs. For example, interpreters are typically significantly hard to understand and hard to reason about. The methodology of “Totally Functional Programming” (TFP) is a reasoned attempt to redress the problem of interpretation. It incorporates an awareness of the undesirability of i...

متن کامل

Approximate Fixed Points in Abstract Interpretation

Much of the earlier development of abstract interpretation, and its application to imperative programming languages, has concerned techniques for finding fixed points in large (often infinite) lattices. The standard approach in the abstract interpretation of functional languages has been to work with small, finite lattices and this supposedly circumvents the need for such techniques. However, p...

متن کامل

Program extraction via typed realisability for induction and coinduction

We study a realisability interpretation for interleaved inductive and coinductive definitions and discuss its application to program extraction in constructive analysis. A speciality of this interpretation is that realisers are given by terms that correspond directly to programs in a lazy functional programming language such as Haskell.

متن کامل

Propagating Diierences: an Eecient New Fixpoint Algorithm for Distributive Constraint Systems

Integrating semi-naive xpoint iteration from deductive data bases 3, 2, 4] as well as continuations into worklist-based solvers, we derive a new application independent local xpoint algorithm for dis-tributive constraint systems. Seemingly diierent eecient algorithms for abstract interpretation like those for linear constant propagation for imperative languages 17] as well as for control-ow ana...

متن کامل

Nordic Journal of Computing PROPAGATING DIFFERENCES: AN EFFICIENT NEW FIXPOINT ALGORITHM FOR DISTRIBUTIVE CONSTRAINT SYSTEMS

Integrating semi-naive xpoint iteration from deductive data bases 3, 2, 4] as well as continuations into worklist-based solvers, we derive a new application independent local xpoint algorithm for distributive constraint systems. Seemingly diierent eecient algorithms for abstract interpretation like those for linear constant propagation for imperative languages 16] as well as for control-ow anal...

متن کامل

ذخیره در منابع من


  با ذخیره ی این منبع در منابع من، دسترسی به آن را برای استفاده های بعدی آسان تر کنید

عنوان ژورنال:

دوره   شماره 

صفحات  -

تاریخ انتشار 2003